#include "cc_mutex.h"
#include "cc_log.h"

void cc_mutex_init(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return;
  }
  (void)xSemaphoreCreateMutexStatic(&mut->mut);
}

cc_mutex_t cc_mutex_create()
{
  cc_mutex_t mut = (cc_mutex_t)cc_malloc(sizeof(cc_mutex));
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return CC_NULL;
  }
  cc_mutex_init(mut);
  return mut;
}

int cc_mutex_lock_time(cc_mutex_t mut, int ms)
{
  if (mut)
  {
    if (cc_is_in_isr())
    {
      BaseType_t xHigherPriorityTaskWoken;
      int status = xSemaphoreTakeFromISR((SemaphoreHandle_t)&mut->mut, &xHigherPriorityTaskWoken);
      portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
      return status;
    }
    return xSemaphoreTake((SemaphoreHandle_t)&mut->mut, ms);
  }

  else
  {
    cc_log_e("mut mem null\r\n");
    return CC_ENOMEM;
  }
}

int cc_mutex_lock(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return CC_ENOMEM;
  }
  return xSemaphoreTake((SemaphoreHandle_t)&mut->mut, CC_TIME_WAIT_FOREVER);
}

int cc_mutex_trylock(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return CC_ENOMEM;
  }
  return xSemaphoreTake((SemaphoreHandle_t)&mut->mut, 0);
}

int cc_mutex_unlock(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return CC_ENOMEM;
  }
  if (cc_is_in_isr())
  {
    BaseType_t xHigherPriorityTaskWoken;
    int status = xSemaphoreGiveFromISR((SemaphoreHandle_t)&mut->mut, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
    return status;
  }
  return xSemaphoreGive((SemaphoreHandle_t)&mut->mut);
}

void cc_mutex_deinit(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return;
  }
  vSemaphoreDelete((SemaphoreHandle_t)&mut->mut);
}

void cc_mutex_destory(cc_mutex_t mut)
{
  if (mut == CC_NULL)
  {
    cc_log_e("mut is null\r\n");
    return;
  }
  cc_mutex_deinit(mut);
  cc_free(mut);
}